package com.koi.resultex.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.koi.common.resultex.ErrorHandler;
import com.koi.common.resultex.R;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @Description: 全局统一返回类
 * bug: (basePackages = "com.koi")建议扫包
 * 为什么？
 * 如果你项目中没有使用Swagger，你可以扫包也可以不扫。都是正常的。
 * 但是如果你项目使用了Swagger，因为Swagger本身也是一个springmvc的项目，他里面也是一个个http请求
 * 这个请求的时候如果你项目中配置了拦截器，或者一些通知类xxxAdvice，那么就会把Swagger都会进行拦截。
 * 就会造成Swagger失效。
 * 解决knife4j失效问题：(basePackages = { "com.koi" }, annotations = { RestController.class })
 */
@RestControllerAdvice(basePackages = { "com" }, annotations = { RestController.class })
public class ResultResponseHandler implements ResponseBodyAdvice<Object> {

    /**
     * 是否支持advice功能，true是支持 false是不支持
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> koiClass) {
        return true;
    }

    /* 参数body 代表其实就是SpringMvc的请求的方法的结果 */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> koiClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        /* 对请求的结果在这里统一返回和处理 */
        if (body instanceof ErrorHandler errorHandler) {
            // 1、如果返回的结果是一个异常的结果，就把异常返回的结构数据倒腾到R.fail里面即可
            return R.error(errorHandler.getStatus(), errorHandler.getMsg());
        } else if (body instanceof R) {
            return body;
        } else if (body instanceof String) {
            try {
                // 2、因为SpringMvc数据转换器对String是有特殊处理 StringHttpMessageConverter，解决String类型的返回
                ObjectMapper objectMapper = new ObjectMapper();
                R r = R.success(body);
                return objectMapper.writeValueAsString(r);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return R.success(body);
    }

}
